/**
 * 
 */
package br.ufrgs.inf.cwsmart;

import javax.naming.OperationNotSupportedException;

import br.ufrgs.inf.cwsmart.api.ExtensionFactory;
import br.ufrgs.inf.cwsmart.data.DataMartManager;
import br.ufrgs.inf.cwsmart.data.RepositoryManager;
import br.ufrgs.inf.cwsmart.description.Description;
import br.ufrgs.inf.cwsmart.exception.FrameworkException;
import br.ufrgs.inf.cwsmart.management.Management;
import br.ufrgs.inf.cwsmart.matcher.MartProperties;
import br.ufrgs.inf.cwsmart.matcher.Matcher;
import br.ufrgs.inf.cwsmart.mining.Mining;
import br.ufrgs.inf.cwsmart.monitoring.Monitoring;
import br.ufrgs.inf.cwsmart.recommendation.Recommendation;
import br.ufrgs.inf.cwsmart.util.Logger;

/**
 * The main class of the framework.
 * 
 * @author Rodrigo S Lumertz
 *
 */
public class CWSMartFramework {	
	
	/**
	 * Singleton framework instance
	 */
	private static CWSMartFramework frameworkInstance;
	
	/**
	 * Singleton repository manager instance
	 */
	private RepositoryManager repositoryManagerInstance;
	
	/**
	 * Singleton repository manager instance
	 */
	private DataMartManager dataMartManagerInstance;
	
	/**
	 * Singleton matcher module
	 */
	private Matcher matcherInstance;
	
	/**
	 * Singleton description module
	 */
	private Description descriptionInstance;
	
	/**
	 * Singleton recommendation module
	 */
	private Recommendation recommendationInstance;
	
	/**
	 * Singleton management module
	 */
	private Management managementInstance;
		
	/*
	 * Singleton mining module
	 */
	private Mining miningInstance;
	
	/*
	 * Singleton mining module
	 */
	private Monitoring monitoringInstance;
	
	/*
	 * Singleton mining module
	 */
	private MartProperties martPropertiesInstance;
	
	/**
	 * The constructor.
	 * 
	 * @param extensionClassName The current class that implements ExtensionFactory abstract class.
	 */
	public CWSMartFramework(String extensionClassName) {
		try {
			Logger.logger.log(Logger.DEBUG1_LEVEL, "CWSMartFramework", "Instantiating the framework");
			
			Logger.logger.log(Logger.DEBUG2_LEVEL, "CWSMartFramework", "Instantiating the concrete Extension Factory");
			ExtensionFactory.init(extensionClassName);			
			
			Logger.logger.log(Logger.DEBUG2_LEVEL, "CWSMartFramework", "Extension factory obtained");
			
			frameworkInstance = this;		
		}
		catch (Exception e) {			
			Logger.logger.log(Logger.WARNING_LEVEL, "CWSMartFramework", "Error: " + e.getMessage());
			System.exit(2);
		}
	}
	
	/**
	 * 
	 * @return
	 * @throws OperationNotSupportedException
	 */
	public static CWSMartFramework getInstance() 
		throws FrameworkException {
		
		if (frameworkInstance != null) {
			return frameworkInstance;
		} else {
			throw new FrameworkException(FrameworkException.ErrorCode.ILLEGAL_FRAMEWORK_ACCESS);
		}
	}
	
	/**
	 * Gets a singleton instance of the repository manager
	 * 
	 * @return The repository manager
	 */
	public RepositoryManager getRepositoryManagerInstance() {
		
		if (repositoryManagerInstance == null) {
			Logger.logger.log(Logger.DEBUG2_LEVEL, "CWSMartFramework", "Instantiating the RepositoryManager");
			repositoryManagerInstance = ExtensionFactory.getExtensionFactory().createRepositoryManager();
		}
		
		return repositoryManagerInstance;
	}
	
	/**
	 * Gets a singleton instance of the datamart manager
	 * 
	 * @return The datamart manager
	 */
	public RepositoryManager getDataMartManagerInstance() {
		
		if (dataMartManagerInstance == null) {
			Logger.logger.log(Logger.DEBUG2_LEVEL, "CWSMartFramework", "Instantiating the DataMartManager");
			dataMartManagerInstance = ExtensionFactory.getExtensionFactory().createDataMartManager();
		}
		
		return repositoryManagerInstance;
	}
	
	/**
	 * Gets a singleton instance of the matcher module
	 * 
	 * @return The matcher module
	 */
	public Matcher getMatcherInstance() {		
		
		if (matcherInstance == null) {
			Logger.logger.log(Logger.DEBUG2_LEVEL, "CWSMartFramework", "Instantiating the Matcher module");
			matcherInstance = ExtensionFactory.getExtensionFactory().createCWSMatcher();
		}
		
		return matcherInstance;
	}
	
	/**
	 * Gets a singleton instance of the description module
	 * 
	 * @return The description module
	 */
	public Description getDescriptionInstance() {
		
		if (descriptionInstance == null) {
			Logger.logger.log(Logger.DEBUG2_LEVEL, "CWSMartFramework", "Instantiating the Description module");
			descriptionInstance = ExtensionFactory.getExtensionFactory().createCWSDescription();
		}
		
		return descriptionInstance;
	}
	
	/**
	 * Gets a singleton instance of the recommendation module
	 * 
	 * @return The recommendation module
	 */
	public Recommendation getRecommendationInstance() {
		
		if (recommendationInstance == null) {
			Logger.logger.log(Logger.DEBUG2_LEVEL, "CWSMartFramework", "Instantiating the Recommendation module");
			recommendationInstance = ExtensionFactory.getExtensionFactory().createCWSRecommendation();
		}
		
		return recommendationInstance;
	}
	
	/**
	 * Gets a singleton instance of the management module
	 * 
	 * @return The management module
	 */
	public Management getManagementInstance() {		
		
		if (managementInstance == null) {			
			Logger.logger.log(Logger.DEBUG2_LEVEL, "CWSMartFramework", "Instantiating the Management module");
			managementInstance = ExtensionFactory.getExtensionFactory().createCWSManagement();
		}
		
		return managementInstance;
	}
	
	/**
	 * Gets a singleton instance of the mining module
	 * 
	 * @return The mining module 
	 */
	public Mining getMiningInstance() {
		
		if (miningInstance == null) {
			Logger.logger.log(Logger.DEBUG2_LEVEL, "CWSMartFramework", "Instantiating the Mining module");
			miningInstance = ExtensionFactory.getExtensionFactory().createCWSMining(); 
		}
		
		return miningInstance;
	}
	
	/**
	 * Gets a singleton instance of the monitoring module
	 * 
	 * @return The monitoring module 
	 */
	public Monitoring getMonitoringInstance() {
		
		if (monitoringInstance == null) {
			Logger.logger.log(Logger.DEBUG2_LEVEL, "CWSMartFramework", "Instantiating the Monitoring module");
			monitoringInstance = ExtensionFactory.getExtensionFactory().createCWSMonitoring();
		}	
		
		return monitoringInstance;
	}
	
	/**
	 * Gets a singleton instance of the mart properties
	 * 
	 * @return The mart properties 
	 * @throws FrameworkException 
	 */
	public MartProperties getMartPropertiesInstance() 
		throws FrameworkException {
		
		if (martPropertiesInstance == null) {
			Logger.logger.log(Logger.DEBUG2_LEVEL, "CWSMartFramework", "Instantiating the MatcherProperties");
			martPropertiesInstance = ExtensionFactory.getExtensionFactory().createMartProperties();
		}
		
		return martPropertiesInstance;
	}
}
